#include "emptybottledetector.h"
#include <QDebug>

EmptyBottleDetector::EmptyBottleDetector()
{
    m_filter = new LowPassFilter<double>(5, 1);
    m_filter->setEnable(true);

    clear();
}

EmptyBottleDetector::~EmptyBottleDetector()
{

}

void EmptyBottleDetector::setEnable(bool en)
{
    m_isEnable = en;
}

bool EmptyBottleDetector::isEnable() const
{
    return m_isEnable;
}

void EmptyBottleDetector::setReStart(bool en)
{
    m_isRestart = en;

    if (m_isRestart)
    {
        m_max.setY(qQNaN());
        m_status = 0;

        m_restartCnt = 20 * m_maskTime; // 前m_restartCnt个数据不处理
    }
}

void EmptyBottleDetector::addData(const double data)
{
    m_cnt++;
    m_cntInPeriod++;

    m_current.setX(m_cnt);
    m_current.setY(data);

    if (qIsNaN(m_max.y()))
    {
        m_max.setX(m_cnt);
        m_max.setY(data);
    }
    else if (data > m_max.y())
    {
        m_max.setX(m_cnt);
        m_max.setY(data);
    }

    // 前m_restartCnt个数据不处理
    if (m_isRestart)
    {
        if (m_restartCnt <= 0)
            m_isRestart = false;
        else
        {
            m_restartCnt--;
            return;
        }
    }
}

#define DONOT_TRIM_BUFFER 0
bool EmptyBottleDetector::detect()
{
    // 统计每圈总点数
    m_periodCnt++;
    m_periodCntBuffer << QPointF(m_periodCnt, m_cntInPeriod);
#if !DONOT_TRIM_BUFFER
    if (m_periodCntBuffer.size() > 50)
        m_periodCntBuffer.removeFirst();
#endif
    m_cntInPeriod = 0;

    // 清除最大值点
    QPointF max = m_max;
    m_max.setY(qQNaN());

    if (!m_isEnable)
        return false;

    // 滤波
    max.setY(m_filter->filter(max.y()));

    // 保存最大值到缓冲区
    if (m_maxBuffer.isEmpty())
    {
        m_maxBuffer << max;
        return false;
    }
    m_maxBuffer << max;
    if (m_maxBuffer.size() < 12)
        return false;
#if !DONOT_TRIM_BUFFER
    m_maxBuffer.removeFirst();
#endif

    // 计算一阶差分并保存
    int len = m_maxBuffer.size();
    double delta = m_maxBuffer.at(len - 1).y() - m_maxBuffer.at(len - 11).y();
    m_deltaBuffer << QPointF(max.x(), delta);
    if (m_deltaBuffer.size() < 10)
        return false;
#if !DONOT_TRIM_BUFFER
    m_deltaBuffer.removeFirst();
#endif

    // 计算二阶差分并保存
    len = m_deltaBuffer.size();
    delta = m_deltaBuffer.at(len - 1).y() - m_deltaBuffer.at(len - 2).y();
    m_delta2Buffer << QPointF(max.x(), delta);
    if (m_delta2Buffer.size() < 2)
        return false;
#if !DONOT_TRIM_BUFFER
    m_delta2Buffer.removeFirst();
#endif

    if (m_delta2Buffer.last().y() < 0)
    {
        m_status++;
    }
    else
    {
        if (m_status)
            m_status--;
    }
    if (m_status > 7 && m_deltaBuffer.last().y() <= -50)
    {
//        m_status = 0;
//        clear();
        qDebug() << "_____empty bottle_______"
                 << m_maxBuffer.last()
                 << m_deltaBuffer.last()
                 << m_delta2Buffer.last();
        return true;
    }
    return false;
}

double EmptyBottleDetector::getStatus() const
{
    return m_status;
}

void EmptyBottleDetector::clear()
{
    m_cnt = 0;
    m_periodCnt = 0;
    m_cntInPeriod = 0;

    m_maxBuffer.clear();
    m_deltaBuffer.clear();
    m_delta2Buffer.clear();
    m_periodCntBuffer.clear();

    m_max.setY(qQNaN());

    m_status = 0;
}

void EmptyBottleDetector::setPressureThreshold(double pressureLow_kPa, double pressureHigh_kPa)
{
    m_pressureThresholdLow = pressureLow_kPa;
    m_pressureThresholdHigh = pressureHigh_kPa;
}

void EmptyBottleDetector::getPressureThreshold(double &pressureLow, double &pressureHigh)
{
    pressureLow = m_pressureThresholdLow;
    pressureHigh = m_pressureThresholdHigh;
}

void EmptyBottleDetector::setMaskTime(int second)
{
    m_maskTime = second;

    if (m_isRestart)
        setReStart(true);
}

int EmptyBottleDetector::getMaskTime()
{
    return m_maskTime;
}

QPointF EmptyBottleDetector::getCurrent() const
{
    return m_current;
}

QPointF EmptyBottleDetector::getMax() const
{
    if (m_maxBuffer.size())
        return m_maxBuffer.last();
    return QPointF(qQNaN(), qQNaN());
}

QPointF EmptyBottleDetector::getDelta() const
{
    if (m_deltaBuffer.size())
        return m_deltaBuffer.last();
    return QPointF(qQNaN(), qQNaN());
}

QPointF EmptyBottleDetector::getDelta2() const
{
    if (m_delta2Buffer.size())
        return m_delta2Buffer.last();
    return QPointF(qQNaN(), qQNaN());
}

QPointF EmptyBottleDetector::getPeriodCnt() const
{
    if (m_periodCntBuffer.size())
        return m_periodCntBuffer.last();
    return QPointF(qQNaN(), qQNaN());
}

QList<QPointF> EmptyBottleDetector::getMaxBuffer() const
{
    return m_maxBuffer;
}

QList<QPointF> EmptyBottleDetector::getDeltaBuffer() const
{
    return m_deltaBuffer;
}

QList<QPointF> EmptyBottleDetector::getDelta2Buffer() const
{
    return m_delta2Buffer;
}

QList<QPointF> EmptyBottleDetector::getPeriodCntBuffer() const
{
    return m_periodCntBuffer;
}

void EmptyBottleDetector::print()
{
    qDebug() << "m_pressureThresholdLow = " << m_pressureThresholdLow << "(kPa), "
             << "m_pressureThresholdHigh = " << m_pressureThresholdHigh << "(kPa), "
             << "m_maskTime = " << m_maskTime << "(s), "
             << "m_periodCnt = " << m_periodCnt << " ";
}
